package com.yanyuhang;

import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.util.Hashtable;

/**
 * @author yyh
 * @create 2021-01-24 9:01
 */
public class LDAPAuthentication {

    private final String URL = "ldap://192.168.157.101:389/";
    private final String BASEDN = "dc=yyh,dc=com"; // 根据自己情况进行修改
    private final String FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
    private LdapContext ctx = null;
    private final Control[] connCtls = null;


    /**
     *
     * @Title: LDAP_connect
     * @Description: 连接
     * @param:
     */
    private Hashtable<String,String> env(){
        Hashtable<String, String> env = new Hashtable<String, String>();
        env.put(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
        env.put(Context.PROVIDER_URL, URL + BASEDN);
        env.put(Context.SECURITY_AUTHENTICATION, "simple");

        String root = "cn=admin,dc=yyh,dc=com"; // 根据自己情况修改
        env.put(Context.SECURITY_PRINCIPAL, root); // 管理员
        env.put(Context.SECURITY_CREDENTIALS, "ldap123"); // 管理员密码

        return env;

    }

    /**
     *
     * @Description: 连接,对应的LDAP环境，比如说LDAP实例
     * @param:
     */
    private LdapContext LDAP_connect() {

        Hashtable<String, String> env = env();

        try {
            ctx = new InitialLdapContext(env, connCtls);
            System.out.println("连接成功");

        } catch (javax.naming.AuthenticationException e) {
            System.out.println("连接失败：");
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("连接出错：");
            e.printStackTrace();
        }

        return ctx;

    }

    /**
     *
     * @Description: 连接,对应的普通环境，比如文件
     * @param:
     */
    private Context LDAP_connect2() {

        Hashtable<String, String> env = env();
        Context ctx2 = null;
        try {
            ctx2 = new InitialContext(env);
            System.out.println("连接成功");

        } catch (javax.naming.AuthenticationException e) {
            System.out.println("连接失败：");
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("连接出错：");
            e.printStackTrace();
        }

        return ctx2;

    }

    /**
     *
     * @Description: 连接,对应的目录环境，比如说文件目录
     * @param:
     */
    private DirContext LDAP_connect3() {

        Hashtable<String, String> env = env();
        DirContext ctx3 = null;
        try {
            ctx3 = new InitialDirContext(env);
            System.out.println("连接成功");

        } catch (javax.naming.AuthenticationException e) {
            System.out.println("连接失败：");
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("连接出错：");
            e.printStackTrace();
        }

        return ctx3;

    }

    /**
     *
     * @Title: closeContext
     * @Description: 关闭
     * @param:
     */
    private void closeContext() {
        if (ctx != null) {
            try {
                ctx.close();
            } catch (NamingException e) {
                e.printStackTrace();
            }

        }
    }

    /**
     *
     * @Title: getUserDN
     * @Description: 查找用户
     * @param: @param  uid
     * @param: @return
     */
    private String getUserDN(String uid) {
        String userDN = "";
        LDAP_connect();
        try {
            SearchControls constraints = new SearchControls();
            constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);

            NamingEnumeration<SearchResult> en = ctx.search("", "uid=" + uid, constraints);

            if (en == null || !en.hasMoreElements()) {
                System.out.println("未找到该用户");
            }
            // maybe more than one element
            while (en != null && en.hasMoreElements()) {
                Object obj = en.nextElement();
                if (obj instanceof SearchResult) {
                    SearchResult si = (SearchResult) obj;
                    userDN += si.getName();
                    userDN += "," + BASEDN;
                } else {
                    System.out.println(obj);
                }
            }
        } catch (Exception e) {
            System.out.println("查找用户时产生异常。");
            e.printStackTrace();
        }

        return userDN;
    }

    /**
     *
     * @Title: authenricate
     * @Description: 验证
     * @param: @param  UID
     * @param: @param  password
     * @param: @return
     */
    public boolean authenricate(String UID, String password) {
        boolean valide = false;
        String userDN = getUserDN(UID);

        try {
            ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
            ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
            ctx.reconnect(connCtls);
            System.out.println(userDN + " 验证通过");
            valide = true;
        } catch (AuthenticationException e) {
            System.out.println(userDN + " 验证失败");
            System.out.println(e.toString());
            valide = false;
        } catch (NamingException e) {
            System.out.println(userDN + " 验证失败");
            valide = false;
        }
        closeContext();
        return valide;
    }

    /**
     *
     * @Title: addUser
     * @Description: 添加用户
     * @param: @param  usr
     * @param: @param  pwd
     * @param: @return
     */
    private boolean addUser(String usr, String pwd) {

        try {
            LDAP_connect();
            BasicAttributes attrsbu = new BasicAttributes();
            BasicAttribute objclassSet = new BasicAttribute("objectclass");
            objclassSet.add("inetOrgPerson");
            attrsbu.put(objclassSet);
            attrsbu.put("sn", usr);
            attrsbu.put("cn", usr);
            attrsbu.put("uid", usr);
            attrsbu.put("sex", "男");
            attrsbu.put("userPassword", pwd);
            //创建当前目录上下文（DirContext）的下一层目录
            //destorySubcontext删除当前目录上下文（DirContext）的下一层目录
            ctx.createSubcontext("uid=" + usr, attrsbu);

            return true;
        } catch (NamingException ex) {
            ex.printStackTrace();
        }
        closeContext();
        return false;
    }

    public static void main(String[] args) {
        LDAPAuthentication ldap = new LDAPAuthentication();
        ldap.LDAP_connect2();
        ldap.addUser("test2", "123456");
        System.out.println("成功");

//        DirContext ldapContext = ldap.LDAP_connect3();
//        Fruit fruit = new Fruit("orange");
//        try {
//            ldapContext.bind("yyh",fruit);
//
//            Object favorite = ldapContext.lookup("yyh");
//            System.out.println(favorite);
//        } catch (NamingException e) {
//            e.printStackTrace();
//        }

//        try {
//            Object test = ldapContext.lookup("uid=test");
//            System.out.println(test);
//        } catch (NamingException e) {
//            e.printStackTrace();
//        }


//        try {
//            //列出所有绑定关系
//            NamingEnumeration<Binding> bindings= ldapContext.listBindings("");
//            while(bindings.hasMore()){
//                Binding binding = bindings.nextElement();
//                System.out.println("Name = "+binding.getName()+", Class = "+ binding.getClassName()+", Object = "+ binding.getObject());
//            }
//
//            //列出所有绑定的名字与类
//            NamingEnumeration<NameClassPair> list = ldapContext.list("");
//            while(list.hasMore()){
//                NameClassPair next = list.next();
//                System.out.println("Name = "+ next.getName()+", Class = "+next.getClassName());
//            }
//        } catch (NamingException e) {
//            e.printStackTrace();
//        }



//        try {
//            //查阅与修改属性
//            //遍历对象的所有属性值
//            Attributes attr = ldapContext.getAttributes("cn=admin");
//
//            //获取所有属性
//            NamingEnumeration<?> ae = attr.getAll();
//            while (ae.hasMore()){
//                Attribute next = (Attribute) ae.next();
//                System.out.println("attribute: "+ next.getID());
//
//                //获取所有值
//                NamingEnumeration<?> e = next.getAll();
//                while(e.hasMore()){
//                    System.out.println("value: "+ e.next());
//                }
//            }
//        } catch (NamingException e) {
//            e.printStackTrace();
//        }

//        String name = "uid=test";
//
//        try {
//            ldapContext.getAttributes(name,new String[]{"telephonenumber","SDKnumber"});
//
//            BasicAttributes newAttrs = new BasicAttributes();
//
//            newAttrs.put(new BasicAttribute("telephonenumber","13254"));
//            newAttrs.put(new BasicAttribute("SDKnumber","255"));
//        } catch (NamingException e) {
//            e.printStackTrace();
//        }

    }
}